package com.gzhryc.shared_device.bxscn.code;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.bxscn.code.dao.db.*;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNOrderEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.PortableEnergyBatteryEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.PortableEnergyCabinetEnum;
import com.gzhryc.shared_device.bxscn.code.services.*;
import com.gzhryc.shared_device.bxscn.code.services.models.BXSCNOpenSlotCacheData;
import com.gzhryc.shared_device.bxscn.core.IBXSCNNetworkEventListener;
import com.gzhryc.shared_device.bxscn.core.enums.EBXSCNLeaseResultCode;
import com.gzhryc.shared_device.bxscn.core.models.*;
import com.gzhryc.shared_device.iot.code.IIOTLogServer;

import java.util.Date;

public class BXSCNNetworkEventListener implements IBXSCNNetworkEventListener {

    static Logger log = Logger.getLogger(BXSCNNetworkEventListener.class);

    private final String jdbcKey;
    private final OperateInfo operateInfo;
    private final IIOTLogServer iotLogServer;
    private final IBXSCNBusinessEventListener businessEventListener;
    private final IBXSCNCacheManager cacheManager;

    public BXSCNNetworkEventListener(String jdbcKey, IIOTLogServer iotLogServer,
                                     IBXSCNBusinessEventListener businessEventListener, IBXSCNCacheManager cacheManager, OperateInfo operateInfo){
        this.jdbcKey = jdbcKey;
        this.iotLogServer = iotLogServer;
        this.businessEventListener = businessEventListener;
        this.cacheManager = cacheManager;
        this.operateInfo = ClassTools.copy(new OperateInfo(),operateInfo);
        this.operateInfo.setOperator("共享便携式电池网络事件监听程序");
    }

    @Override
    public void leaseReceiveHandle(BXSCNLeaseResult leaseResult) {
        log.info("便携式储能租借结果返回：{{0:json}}",leaseResult);
        BXSCNWorkCacheManager.DeviceWorkInfo deviceWorkInfo = BXSCNWorkCacheManager.self().getAndRemoveData(leaseResult.getDeviceSn(),leaseResult.getMsgId());
        if(deviceWorkInfo == null){
            deviceWorkInfo = new BXSCNWorkCacheManager.DeviceWorkInfo();
            deviceWorkInfo.setDeviceSn(leaseResult.getDeviceSn());
            deviceWorkInfo.setTradeNo(leaseResult.getTradeNo());
            deviceWorkInfo.setSlotNum(leaseResult.getSlotNum());
        }

        BXSCNOrder bxscnOrder = BXSCNOrderService.self(new Date()).getByTradeNo(deviceWorkInfo.getTradeNo());
        if(bxscnOrder != null){
            if(BXSCNOrderEnum.State.Opening.index().equals(bxscnOrder.getState())) {
                //获取电池类型
                bxscnOrder.setLeasePower(leaseResult.getPower());
                bxscnOrder.setPortableBatterySn(leaseResult.getPortableBatterySn());
                bxscnOrder.setLeaseSlotNum(leaseResult.getSlotNum());

                PortableEnergyBattery energyBattery = PortableEnergyBatteryService.self().getByDeviceSn(leaseResult.getPortableBatterySn());
                if(energyBattery != null){
                    bxscnOrder.setBatteryType(energyBattery.getType());
                    bxscnOrder.setBatteryTypeName(energyBattery.getTypeName());
                }else{
                    log.error("未找到电池信息，电池序列号：{{0}}",leaseResult.getPortableBatterySn());
                }

                if (EBXSCNLeaseResultCode.Success.index().equals(leaseResult.getResultCode())) {
                    operateInfo.setOperateNote("便携式储能租借成功通知");
                    BXSCNOrderService.self(bxscnOrder.getCreateDate()).openingSuccess(bxscnOrder, operateInfo);
                    if (!PortableEnergyBatteryService.self().lease(leaseResult.getPortableBatterySn(), bxscnOrder.getTradeNo(),bxscnOrder.getCreateDate())) {
                        log.error("致命错误，修改便携式储能租借信息错误，充电宝ID：{{0}}", leaseResult.getPortableBatterySn());
                    }
                    //清理缓存
                    cacheManager.removePortableEnergyCabinetSlot(leaseResult.getDeviceSn(),leaseResult.getSlotNum());
                } else {
                    operateInfo.setOperateNote(EBXSCNLeaseResultCode.note(leaseResult.getResultCode()));
                    Integer leaseErrorState = BXSCNOrderEnum.LeaseErrorState.NoPortableBattery.index();
                    if(EBXSCNLeaseResultCode.NotRemoved.index().equals(leaseResult.getResultCode())){
                        leaseErrorState = BXSCNOrderEnum.LeaseErrorState.NotRemoved.index();
                    }else if(EBXSCNLeaseResultCode.LockException.index().equals(leaseResult.getResultCode())){
                        leaseErrorState = BXSCNOrderEnum.LeaseErrorState.LockException.index();
                    }else if(EBXSCNLeaseResultCode.Overtime.index().equals(leaseResult.getResultCode())){
                        leaseErrorState = BXSCNOrderEnum.LeaseErrorState.Timeout.index();
                    }
                    BXSCNOrderService.self(bxscnOrder.getCreateDate()).openingFail(bxscnOrder,leaseErrorState,operateInfo);
                }

                businessEventListener.leaseResult(bxscnOrder, leaseResult);
            }else{
                log.error("租借返回时，设备订单状态不对，订单号：{{0}}，订单状态：{{1}}",bxscnOrder.getTradeNo(),bxscnOrder.getStateName()+"("+bxscnOrder.getState()+")");
            }
        }else{
            if (EBXSCNLeaseResultCode.Success.index().equals(leaseResult.getResultCode())) {
                if (!PortableEnergyBatteryService.self().lease(leaseResult.getPortableBatterySn(),leaseResult.getTradeNo(),new Date())) {
                    log.error("致命错误，修改便携式储能租借信息错误，充电宝ID：{{0}}", leaseResult.getPortableBatterySn());
                }
                //清理缓存
                cacheManager.removePortableEnergyCabinetSlot(leaseResult.getDeviceSn(),leaseResult.getSlotNum());
            }
            log.error("租借返回时，未找到设备订单，返回内容：{{0:json}}",leaseResult);
        }
    }

    @Override
    public void openSlotReceiveHandle(BXSCNOpenSlotResult openSlotResult) {
        log.info("便携式储能开仓结果返回：{{0:json}}",openSlotResult);
        BXSCNOpenSlotCacheData openSlotCacheData = cacheManager.getCommandResult(openSlotResult.getDeviceSn(),openSlotResult.getMsgId(),BXSCNOpenSlotCacheData.class);
        if(openSlotCacheData != null){
            openSlotCacheData.setOpenSlotResult(openSlotResult);
            cacheManager.setCommandResult(openSlotResult.getDeviceSn(),openSlotResult.getMsgId(), JsonTools.toJson(openSlotCacheData));
        }
    }

    @Override
    public void searchResultHandle(BXSCNSearchResult searchResult) {
        MultiDBTools.setJdbcKey(jdbcKey);
        try {
            //不使用缓存，强制更新
            PortableEnergyCabinet portableEnergyCabinet = PortableEnergyCabinetService.self().getByDeviceSn(searchResult.getDeviceSn());
            if (portableEnergyCabinet != null) {
                PortableEnergyCabinetService.self().online(portableEnergyCabinet.getDeviceSn(),searchResult.getVersionNumber(),searchResult.getImsi()
                        ,searchResult.getIccid(),searchResult.getRssi());
                portableEnergyCabinet.setState(PortableEnergyCabinetEnum.State.Online.index());
                portableEnergyCabinet.setHeartbeatData(new Date());
                cacheManager.savePortableEnergyCabinet(portableEnergyCabinet);
            }

            if (portableEnergyCabinet != null) {
                for (Integer slotNum = 1; slotNum <= portableEnergyCabinet.getSlotTotal(); slotNum++) {
                    BXSCNSearchResult.SlotItem slotItem = null;
                    if (searchResult.getItems() != null && searchResult.getItems().size() > 0) {
                        for (BXSCNSearchResult.SlotItem item : searchResult.getItems()) {
                            if (item.getSlotNum().equals(slotNum)) {
                                slotItem = item;
                                break;
                            }
                        }
                    }
                    PortableEnergyCabinetSlot batteryCabinetSlot = PortableEnergyCabinetSlotService.self().getOrAddByKeys(searchResult.getDeviceSn(), slotNum);
                    if (batteryCabinetSlot == null) {
                        log.error("共享便携式电池设备查询，获取或新增卡槽信息失败，设备序列号：{{0}}，卡槽：{{1}}", searchResult.getDeviceSn(), slotNum);
                        continue;
                    }

                    if (slotItem != null) {
                        if (StringTools.isNotBlank(slotItem.getSubDeviceSn())) {
                            //查询结果与数据库保存的充电宝不一致
                            if (StringTools.isBlank(batteryCabinetSlot.getPortableBatterySn()) ||
                                    !batteryCabinetSlot.getPortableBatterySn().equals(slotItem.getSubDeviceSn())) {
                                batteryCabinetSlot.setPortableBatterySn(slotItem.getSubDeviceSn());
                                if (!PortableEnergyCabinetSlotService.self().updateNotNull(batteryCabinetSlot)) {
                                    log.error("共享便携式电池设备查询，修改槽信息失败，设备序列号：{{0}}，卡槽：{{1}}", searchResult, slotNum);
                                }
                            }

                            PortableEnergyBattery portableBattery = PortableEnergyBatteryService.self().getByDeviceSn(slotItem.getSubDeviceSn());
                            if (portableBattery == null) {
                                //随机一个设备类型
                                PortableEnergyBatteryType portableEnergyBatteryType = PortableEnergyBatteryTypeService.self().getByDefault();
                                if (portableEnergyBatteryType == null) {
                                    log.error("未找到默认的便携式电池类型");
                                }
                                portableBattery = new PortableEnergyBattery();
                                portableBattery.setDeviceSn(slotItem.getSubDeviceSn());
                                portableBattery.setPower(slotItem.getPower());
                                portableBattery.setType(portableEnergyBatteryType.getId());
                                portableBattery.setTypeName(portableEnergyBatteryType.getName());
                                portableBattery.setCabinetDeviceSn(searchResult.getDeviceSn());
                                portableBattery.setSlotNum(slotNum);
                                portableBattery.setState(PortableEnergyBatteryEnum.State.Charging.index());
                                portableBattery.setLastHeartDate(new Date());
                                if (!PortableEnergyBatteryService.self().add(portableBattery)) {
                                    log.error("共享便携式电池设备查询，新增便携式电池失败，设备序列号：{{0}}，卡槽：{{1}}，便携式电池ID：{{2}}", searchResult, slotNum, slotItem.getSubDeviceSn());
                                }
                            } else {
                                //检查是否需要更新
                                boolean flag = false;
                                if (StringTools.isBlank(portableBattery.getCabinetDeviceSn())
                                        || !portableBattery.getCabinetDeviceSn().equals(portableEnergyCabinet.getDeviceSn())) {
                                    flag = true;
                                }
                                if (!flag && portableBattery == null && !portableBattery.getSlotNum().equals(slotItem.getSlotNum())) {
                                    flag = true;
                                }
                                if (!flag && portableBattery.getPower() == null && !portableBattery.getPower().equals(slotItem.getPower())) {
                                    flag = true;
                                }
                                if (!flag && !PortableEnergyBatteryEnum.State.Charging.index().equals(portableBattery.getState())) {
                                    flag = true;
                                }

                                if (flag) {
                                    if (!PortableEnergyBatteryService.self().revert(portableBattery.getDeviceSn(), portableEnergyCabinet.getDeviceSn()
                                            , slotItem.getSlotNum(), slotItem.getPower())) {
                                        log.error("查询共享便携式电池时，更新便携式电池信息失败，充电宝ID：{{0}}", portableBattery.getDeviceSn());
                                    }
                                }
                            }
                            batteryCabinetSlot.setPortableBattery(portableBattery);
                        } else if (StringTools.isNotBlank(batteryCabinetSlot.getPortableBatterySn())) {
                            if (!PortableEnergyCabinetSlotService.self().removePortableBatterySn(searchResult.getDeviceSn(), slotNum)) {
                                log.error("共享便携式电池设备查询，移除卡槽中便携式电池失败，设备序列号：{{0}}，卡槽：{{1}}，便携式电池ID：{{2}}", searchResult.getDeviceSn(), slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                            if (!PortableEnergyBatteryService.self().eject(batteryCabinetSlot.getPortableBatterySn())) {
                                log.error("共享便携式电池设备查询，修改便携式电池弹出失败，设备序列号：{{0}}，卡槽：{{1}}，便携式电池ID：{{2}}", searchResult.getDeviceSn(), slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                            batteryCabinetSlot.setPortableBatterySn(null);
                        }
                        cacheManager.savePortableEnergyCabinetSlot(batteryCabinetSlot);
                    } else {
                        if (StringTools.isNotBlank(batteryCabinetSlot.getPortableBatterySn())) {
                            if (!PortableEnergyCabinetSlotService.self().removePortableBatterySn(searchResult.getDeviceSn(), slotNum)) {
                                log.error("共享便携式电池设备查询，移除卡槽中充电宝失败，设备序列号：{{0}}，卡槽：{{1}}，便携式电池ID：{{2}}", searchResult.getDeviceSn(), slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                            if (!PortableEnergyBatteryService.self().eject(batteryCabinetSlot.getPortableBatterySn())) {
                                log.error("共享便携式电池设备查询，修改充电宝弹出失败，设备序列号：{{0}}，卡槽：{{1}}，便携式电池ID：{{2}}", searchResult.getDeviceSn(), slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                        }
                        cacheManager.removePortableEnergyCabinetSlot(searchResult.getDeviceSn(), batteryCabinetSlot.getSlotNum());
                    }
                }
            } else {
                log.error("共享便携式电池设备查询结果，未找到设备信息，报文：{{0:json}}", searchResult);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            JdbcSession.clear();
            MultiDBTools.removeJdbcKey();
        }
    }

    @Override
    public void ejectReceiveHandle(BXSCNEjectResult ejectResponse) {

    }

    @Override
    public void returnHandle(BXSCNReturnNotify returnNotify) {
        log.info("便携式电池归还通知：{{0:json}}",returnNotify);
        PortableEnergyBattery portableBattery = PortableEnergyBatteryService.self().getByDeviceSn(returnNotify.getPortableBatterySn());
        if(portableBattery == null){
            log.error("未知道的便携式电池ID，归还信息：{{0:json}}",returnNotify);
        }
        if(!PortableEnergyBatteryService.self().revert(returnNotify.getPortableBatterySn(),returnNotify.getDeviceSn()
                ,returnNotify.getSlotNum(),returnNotify.getPower())){
            log.error("致命错误，修改便携式电池归还信息失败，便携式电池ID：{{0}}",returnNotify.getPortableBatterySn());
        }
        if(StringTools.isNotBlank(portableBattery.getCurrentTradeNo())){
            BXSCNOrder cdbOrder = BXSCNOrderService.self(new Date()).getByTradeNo(portableBattery.getCurrentTradeNo());
            if(cdbOrder != null){
                if(!BXSCNOrderEnum.State.RevertFinish.index().equals(cdbOrder.getState())){
                    businessEventListener.revertResult(cdbOrder,portableBattery,returnNotify,operateInfo);
                }
            }
        }
    }

    @Override
    public void heart(String deviceSn, String versionNumber, String imsi, String iccid, Integer rssi) {

    }

    @Override
    public void online(String deviceSn, String versionNumber, String imsi, String iccid, Integer rssi) {

    }

    @Override
    public void offline(String deviceSn) {

    }
}
